<template>
  <!-- 2021.11.18移除voltable方法@cell-mouse-leave="rowEndEdit" -->
  <div
    class="vol-table"
    ref="refTable"
    :class="[
      textInline ? 'text-inline' : '',
      fxRight ? 'fx-right' : '',
      isChrome ? 'chrome' : '',
      smallCell ? 'small-table' : '',
    ]"
  >
    <template v-if="dragPosition">
      <div v-show="showDragMask" class="drag-mask"></div>
    </template>
    <div class="el-drag" ref="drag" v-if="dragPosition == 'top'"></div>
    <!-- loading -->
    <div class="mask" v-show="loading"></div>
    <div class="message" v-show="loading">
      <div>{{ $ts("加载中") }}.....</div>
    </div>
    <el-table
      :show-summary="summary"
      :summary-method="getSummaryData"
      :row-key="rowKey"
      :key="randomTableKey"
      :lazy="lazy"
      :defaultExpandAll="defaultExpandAll"
      :expand-row-keys="rowKey ? expandRowKeys : undefined"
      stripe
      :load="loadTreeChildren"
      @select="userSelect"
      @select-all="userSelect"
      @selection-change="selectionChange"
      @row-dblclick="rowDbClick"
      @row-click="rowClick"
      @header-click="headerClick"
      :highlight-current-row="highlightCurrentRow"
      ref="table"
      class="v-table"
      @sort-change="sortChange"
      tooltip-effect="dark"
      :height="realHeight - extraHeight || null"
      :max-height="realMaxHeight"
      :data="url ? rowData : tableData"
      :border="true"
      :row-class-name="initIndex"
      :cell-style="getCellStyle"
      :cell-class-name="getCellClass"
      style="width: 100%"
      :scrollbar-always-on="true"
      @expand-change="expandChange"
      :span-method="cellSpanMethod"
    >
      <el-table-column
        v-if="columnIndex"
        type="index"
        :fixed="fixed"
        width="55"
        label="#"
      ></el-table-column>
      <el-table-column
        v-if="ck"
        type="selection"
        :fixed="fixed"
        :selectable="selectable"
        width="55"
      ></el-table-column>

      <!-- 2020.10.10移除table第一行强制排序 -->
      <el-table-column
        v-for="(column, cindex) in filterColumns"
        :prop="column.field"
        :label="column.title"
        :min-width="column.width"
        :formatter="formatter"
        :fixed="column.fixed"
        :key="column.field + cindex"
        :align="column.align"
        :sortable="column.sort ? 'custom' : false"
        :show-overflow-tooltip="column.showOverflowTooltip"
        :class-name="column.class"
        :filters="column.filterData ? getFilters(column) : undefined"
        :filter-method="column.filterData ? filterHandler : undefined"
      >
        <template #filter-icon
          ><el-icon><Filter /></el-icon
        ></template>
        <template #header>
          <span
            v-if="(column.require || column.required) && column.edit"
            class="column-required"
            >*</span
          >{{ $ts(column.title) }}
          <el-tooltip placement="top" v-if="column.tip">
            <template #content><div v-html="column.tip.text"></div></template>
            <i
              style="color: #7d7979"
              @click="column.tip.click"
              :class="column.tip.icon || 'el-icon-warning-outline'"
            ></i>
          </el-tooltip>
        </template>

        <template #default="scope">
          <!-- 2022.01.08增加多表头，现在只支持常用功能渲染，不支持编辑功能(涉及到组件重写) -->
          <el-table-column
            style="border: none"
            v-for="columnChildren in filterChildrenColumn(column.children)"
            :key="columnChildren.field"
            :min-width="columnChildren.width"
            :class-name="columnChildren.class"
            :prop="columnChildren.field"
            :align="columnChildren.align"
            :show-overflow-tooltip="columnChildren.showOverflowTooltip"
            :label="$ts(columnChildren.title)"
          >
            <template #default="scopeChildren">
              <a
                v-if="columnChildren.link"
                href="javascript:void(0)"
                style="text-decoration: none"
                @click="link(scopeChildren.row, columnChildren, $event)"
                v-text="scopeChildren.row[columnChildren.field]"
              ></a>
              <div
                v-else-if="columnChildren.formatter"
                @click="
                  columnChildren.click &&
                    columnChildren.click(
                      scopeChildren.row,
                      columnChildren,
                      scopeChildren.$index
                    )
                "
                v-html="
                  columnChildren.formatter(
                    scopeChildren.row,
                    columnChildren,
                    scopeChildren.$index
                  )
                "
              ></div>
              <div v-else-if="columnChildren.bind">
                {{ formatter(scopeChildren.row, columnChildren, true) }}
              </div>
              <span v-else-if="columnChildren.type == 'date'">{{
                formatterDate(scopeChildren.row, columnChildren)
              }}</span>
              <template v-else>
                {{ scopeChildren.row[columnChildren.field] }}
              </template>
            </template>
          </el-table-column>
          <!-- 2020.06.18增加render渲染自定义内容 -->
          <table-render
            v-if="column.render && typeof column.render == 'function'"
            :row="scope.row"
            key="rd-01"
            :index="scope.$index"
            :column="column"
            :render="column.render"
          ></table-render>
          <!-- 启用双击编辑功能，带编辑功能的不会渲染下拉框文本背景颜色 -->
          <!-- @click="rowBeginEdit(scope.$index,cindex)" -->

          <template
            v-else-if="
              column.edit &&
              !column.readonly &&
              ['file', 'img', 'excel'].indexOf(column.edit.type) != -1
            "
          >
            <div style="display: flex; align-items: center" @click.stop>
              <i
                style="padding: 3px; margin-right: 10px; color: #8f9293; cursor: pointer"
                @click="showUpload(scope.row, column)"
                class="el-icon-upload"
              ></i>
              <template v-if="column.edit.type == 'img'">
                <img
                  v-for="(file, imgIndex) in getFilePath(scope.row[column.field], column)"
                  :key="imgIndex"
                  @error="handleImageError"
                  @click="viewImg(scope.row, column, file.path, $event, imgIndex)"
                  class="table-img"
                  :src="file.path + access_token"
                />
              </template>
              <a
                style="margin-right: 8px"
                v-else
                class="t-file"
                v-for="(file, fIndex) in getFilePath(scope.row[column.field], column)"
                :key="fIndex"
                @click="dowloadFile(file)"
                >{{ file.name }}</a
              >
            </div>
          </template>
          <!-- 2021.09.21增加编辑时对readonly属性判断 -->
          <div
            v-else-if="
              column.edit &&
              !column.readonly &&
              (column.edit.keep || edit.rowIndex == scope.$index)
            "
            class="edit-el"
          >
            <div @click.stop class="e-item">
              <div>
                <!-- 2020.07.24增加日期onChange事件 -->
                <el-date-picker
                  clearable
                  size="default"
                  style="width: 100%"
                  :ref="column.field + scope.$index"
                  v-if="['date', 'datetime', 'month'].indexOf(column.edit.type) != -1"
                  v-model="scope.row[column.field]"
                  @click.navigator
                  @change="
                    (val) => {
                      dateChange(scope.row, column, val);
                    }
                  "
                  :type="column.edit.type"
                  :placeholder="$ts(column.placeholder || column.title)"
                  :disabledDate="(val) => getDateOptions(val, column)"
                  :value-format="getDateFormat(column)"
                  :disabled="initColumnDisabled(scope.row, column)"
                  @visible-change="dateVisibleChang"
                >
                </el-date-picker>
                <el-time-picker
                  clearable
                  size="default"
                  style="width: 100%"
                  v-else-if="column.edit.type == 'time'"
                  v-model="scope.row[column.field]"
                  @change="
                    (val) => {
                      column.onChange && column.onChange(scope.row, column, val);
                    }
                  "
                  :placeholder="$ts(column.placeholder || column.title)"
                  :value-format="column.format || 'HH:mm:ss'"
                  :disabled="initColumnDisabled(scope.row, column)"
                >
                </el-time-picker>
                <template v-else-if="column.edit.type == 'color'">
                  {{ scope.row[column.field] }}
                  <el-color-picker
                    @show="isDateChange = true"
                    @hide="isDateChange = false"
                    show-alpha
                    :teleported="true"
                    :predefine="[
                      '#ff4500',
                      '#ff8c00',
                      '#ffd700',
                      '#90ee90',
                      '#00ced1',
                      '#1e90ff',
                      '#c71585',
                    ]"
                    v-model="scope.row[column.field]"
                  />
                </template>
                <el-switch
                  v-else-if="column.edit.type == 'switch'"
                  v-model="scope.row[column.field]"
                  active-color="#0f84ff"
                  inactive-color="rgb(194 194 194)"
                  :active-text="$ts(column.activeText)"
                  :inactive-text="$ts(column.inactiveText)"
                  @change="
                    (val) => {
                      switchChange(val, scope.row, column);
                    }
                  "
                  :active-value="
                    typeof scope.row[column.field] == 'boolean'
                      ? true
                      : typeof scope.row[column.field] == 'string'
                      ? '1'
                      : 1
                  "
                  :inactive-value="
                    typeof scope.row[column.field] == 'boolean'
                      ? false
                      : typeof scope.row[column.field] == 'string'
                      ? '0'
                      : 0
                  "
                  :disabled="initColumnDisabled(scope.row, column)"
                >
                </el-switch>

                <vol-select-table
                  v-else-if="column.edit.type == 'selectTable'"
                  v-model="scope.row[column.field]"
                  :field="column.field"
                  :ref="column.field + scope.$index"
                  :onSelect="
                    (rows) => {
                      column.onSelect && column.onSelect(scope.row, rows);
                    }
                  "
                  :textInline="column.textInline"
                  :paginationHide="column.paginationHide"
                  :pagination="column.pagination"
                  :loadBefore="
                    (params, callBack) => {
                      column.loadBefore && column.loadBefore(scope.row, params, callBack);
                    }
                  "
                  :loadAfter="
                    (rows, callBack, result) => {
                      column.loadAfter &&
                        column.loadAfter(scope.row, rows, callBack, result);
                    }
                  "
                  @onKeyPress="
                    (value, $event) => {
                      column.onKeyPress && column.onKeyPress(value, $event, scope.row);
                    }
                  "
                  :url="column.url"
                  :columns="column.columns"
                  :defaultLoadPage="column.load"
                  :single="column.single"
                  :height="column.height"
                  :input-readonly="column.inputReadonly"
                  :width="column.selectWidth"
                >
                </vol-select-table>

                <template
                  v-else-if="['select', 'selectList'].indexOf(column.edit.type) != -1"
                >
                  <el-select-v2
                    :ref="column.field + scope.$index"
                    style="width: 100%"
                    size="default"
                    v-if="column.bind.data.length >= select2Count"
                    v-model="scope.row[column.field]"
                    :filterable="column.filter === undefined ? true : column.filter"
                    :multiple="column.edit.type == 'select' ? false : true"
                    :placeholder="$ts(column.placeholder || column.title)"
                    :allow-create="column.autocomplete"
                    :options="column.bind.data"
                    @change="column.onChange && column.onChange(scope.row, column)"
                    clearable
                    :disabled="initColumnDisabled(scope.row, column)"
                  >
                    <template #default="{ item }">
                      {{ item.label }}
                    </template>
                  </el-select-v2>

                  <el-select
                    :ref="column.field + scope.$index"
                    size="default"
                    style="width: 100%"
                    v-else
                    v-model="scope.row[column.field]"
                    :filterable="column.filter === undefined ? true : column.filter"
                    :multiple="column.edit.type == 'select' ? false : true"
                    :placeholder="$ts(column.placeholder || column.title)"
                    :allow-create="column.autocomplete"
                    @change="
                      (val) => {
                        selectChange(scope.row, column, val);
                      }
                    "
                    @clear="
                      (val) => {
                        selectChange(scope.row, column, val, true);
                      }
                    "
                    clearable
                    :disabled="initColumnDisabled(scope.row, column)"
                  >
                    <el-option
                      v-for="item in column.bind.data"
                      :key="item.key"
                      v-show="!item.hidden"
                      :disabled="item.disabled"
                      :label="$ts(item.value)"
                      :value="item.key"
                    >
                    </el-option>
                  </el-select>
                </template>
                <el-tree-select
                  :ref="column.field + scope.$index"
                  style="width: 100%"
                  v-else-if="
                    column.edit.type == 'treeSelect' || column.edit.type == 'cascader'
                  "
                  v-model="scope.row[column.field]"
                  :data="column.bind.data"
                  :multiple="column.multiple === undefined ? true : column.multiple"
                  :render-after-expand="false"
                  :show-checkbox="true"
                  :check-strictly="true"
                  check-on-click-node
                  node-key="key"
                  @change="column.onChange && column.onChange(scope.row, column)"
                  :props="{ label: 'label' }"
                >
                  <template #default="{ data, node }"> {{ $ts(data.label) }}</template>
                </el-tree-select>
                <el-input
                  :ref="column.field + scope.$index"
                  v-else-if="column.edit.type == 'textarea'"
                  type="textarea"
                  :placeholder="$ts(column.placeholder || column.title)"
                  v-model="scope.row[column.field]"
                  :disabled="initColumnDisabled(scope.row, column)"
                  :autosize="{
                    minRows: column.minRows || 2,
                    maxRows: column.maxRows || 10,
                  }"
                >
                </el-input>
                <el-input-number
                  :ref="column.field + scope.$index"
                  style="width: 100%"
                  v-else-if="
                    column.edit.type == 'number' || column.edit.type == 'decimal'
                  "
                  v-model="scope.row[column.field]"
                  :precision="column.edit.type == 'number' ? 0 : column.precision"
                  :min="column.min"
                  :disabled="column.readonly || column.disabled"
                  :max="column.max"
                  controls-position="right"
                  @focus="onFocus(scope.row, column, $event)"
                  @blur="onBlur(scope.row, column, $event)"
                  @change="inputKeyPress(scope.row, column, $event)"
                />
                <input
                  :ref="column.field + scope.$index"
                  class="table-input"
                  v-else-if="!column.summary && !column.onKeyPress"
                  v-model.lazy="scope.row[column.field]"
                  :placeholder="$ts(column.placeholder || column.title)"
                  :disabled="initColumnDisabled(scope.row, column)"
                  @input="inputKeyPress(scope.row, column, $event)"
                  @focus="onFocus(scope.row, column, $event)"
                  @blur="onBlur(scope.row, column, $event)"
                />
                <el-input
                  v-else
                  :ref="column.field + scope.$index"
                  @change="inputKeyPress(scope.row, column, $event)"
                  @input="inputKeyPress(scope.row, column, $event)"
                  @keyup.enter="inputKeyPress(scope.row, column, $event)"
                  size="default"
                  v-model="scope.row[column.field]"
                  :placeholder="$ts(column.placeholder || column.title)"
                  :disabled="initColumnDisabled(scope.row, column)"
                  @blur="onBlur(scope.row, column, $event)"
                ></el-input>
              </div>
              <div class="extra" v-if="column.extra && edit.rowIndex == scope.$index">
                <a
                  :style="column.extra.style"
                  style="text-decoration: none"
                  @click="extraClick(scope.row, column)"
                >
                  <i v-if="column.extra.icon" :class="[column.extra.icon]" />
                  {{ column.extra.text }}
                </a>
              </div>
            </div>
          </div>
          <!--没有编辑功能的直接渲染标签-->
          <!-- v-text="scope.row[column.field]" -->
          <template v-else>
            <a
              v-if="column.link"
              href="javascript:void(0)"
              style="text-decoration: none"
              @click="link(scope.row, column, $event)"
              v-text="formatter(scope.row, column, true)"
            ></a>
            <img
              v-else-if="column.type == 'img'"
              v-for="(file, imgIndex) in getFilePath(scope.row[column.field], column)"
              :key="imgIndex"
              @error="handleImageError"
              @click="viewImg(scope.row, column, file.path, $event, imgIndex)"
              class="table-img"
              :style="{
                height: (column.imgHeight || 40) + 'px',
                width: (column.imgWidth || 40) + 'px',
              }"
              :src="file.path + access_token"
            />
            <a
              style="margin-right: 8px"
              v-else-if="column.type == 'file' || column.type == 'excel'"
              class="t-file"
              v-for="(file, fIndex) in getFilePath(scope.row[column.field], column)"
              :key="fIndex"
              @click="dowloadFile(file)"
              >{{ file.name }}</a
            >
            <template v-else-if="column.type == 'date'">{{
              formatterDate(scope.row, column)
            }}</template>
            <template v-else-if="column.type == 'month'">{{
              (scope.row[column.field] || "").substr(0, 7)
            }}</template>
            <div
              v-else-if="column.formatter"
              @click.stop="formatterClick(scope.row, column, $event)"
              v-html="column.formatter(scope.row, column)"
            ></div>
            <!-- 2021.11.18修复table数据源设置为normal后点击行$event缺失的问题 -->
            <div
              v-else-if="column.bind && (column.normal || column.edit)"
              @click.stop="formatterClick(scope.row, column, $event)"
              :style="column.getStyle && column.getStyle(scope.row, column)"
            >
              {{ formatter(scope.row, column, true) }}
            </div>
            <div
              v-else-if="column.click && !column.bind"
              @click="formatterClick(scope.row, column)"
            >
              {{ scope.row[column.field] }}
            </div>
            <div
              @click="
                () => {
                  column.click && formatterClick(scope.row, column);
                }
              "
              v-else-if="column.bind"
            >
              <el-tag
                v-if="useTag && column.type != 'cascader'"
                class="cell-tag"
                :class="[isEmptyTag(scope.row, column)]"
                :type="getColor(scope.row, column)"
                :effect="column.effect"
                >{{ formatter(scope.row, column, true) }}</el-tag
              >
              <template v-else>{{ formatter(scope.row, column, true) }}</template>
            </div>

            <template v-else>{{ formatter(scope.row, column, true) }}</template>
          </template>
        </template>
      </el-table-column>
    </el-table>
    <template v-if="!paginationHide">
      <div class="block pagination" key="pagination-01" style="display: flex">
        <div style="flex: 1"></div>
        <el-pagination
          key="pagination-02"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="paginations.page"
          :page-sizes="paginations.sizes"
          :page-size="paginations.size"
          :pager-count="pagerCount"
          layout="total, sizes, prev, pager, next, jumper"
          :total="paginations.total"
        ></el-pagination>
      </div>
    </template>
    <div class="el-drag" ref="drag" v-if="dragPosition == 'bottom'"></div>

    <VolBox
      v-model="uploadModel"
      title="上传"
      :height="228"
      :width="500"
      :padding="15"
      lazy
    >
      <!-- 上传图片、excel或其他文件、文件数量、大小限制都可以，参照volupload组件api -->
      <div class="vol-table-upload">
        <VolUpload
          style="text-align: center"
          :autoUpload="currentColumn.edit.autoUpload"
          :multiple="currentColumn.edit.multiple"
          :url="uploadUrl"
          :max-file="currentColumn.edit.maxFile"
          :max-size="currentColumn.edit.maxSize"
          :img="currentColumn.edit.type == 'img'"
          :excel="currentColumn.edit.type == 'excel'"
          :fileTypes="currentColumn.edit.fileTypes ? currentColumn.edit.fileTypes : []"
          :fileInfo="fileInfo"
          :upload-before="uploadBefore"
          :upload-after="uploadAfter"
          :onChange="uploadOnChange"
        >
          <div>{{ currentColumn.message }}</div>
        </VolUpload>
      </div>
      <template #footer>
        <div style="text-align: center">
          <el-button type="default" size="small" @click="uploadModel = false">{{
            $ts("关闭")
          }}</el-button>
          <el-button type="primary" size="small" @click="saveUpload">{{
            $ts("保存")
          }}</el-button>
        </div>
      </template>
    </VolBox>
    <vol-image-viewer ref="viewer"></vol-image-viewer>
  </div>
</template>
<script>
import VolTableRender from "./VolTable/VolTableRender";
let _errMsg;
import { defineComponent, defineAsyncComponent } from "vue";
import { default as Sortable } from "sortablejs";
export default defineComponent({
  //https://github.com/element-plus/element-plus/issues/1483
  //没有原先的selection属性了，看issue上使用select/selectall获取
  watch: {
    "tableData.length": {
      handler(newLen, oldLen) {
        this.watchRowSelectChange(newLen, oldLen);
      },
    },
    "rowData.length": {
      handler(newLen, oldLen) {
        this.watchRowSelectChange(newLen, oldLen);
      },
    },
  },
  components: {
    "vol-image-viewer": defineAsyncComponent(() =>
      import("@/components/basic/VolImageViewer.vue")
    ),
    "table-render": VolTableRender,
    VolUpload: defineAsyncComponent(() => import("@/components/basic/VolUpload.vue")),
    VolBox: defineAsyncComponent(() => import("@/components/basic/VolBox.vue")),
  },
  props: {
    rowKey: {
      // 树形结构的主键字段，如果设置值默认会开启树形table；注意rowKey字段的值必须是唯一（2021.05.02）
      typeof: String,
      default: undefined,
    },
    loadTreeChildren: {
      // 树形结构加载子节点
      type: Function,
      default: (tree, treeNode, resolve) => {
        if (resolve) {
          return resolve([]);
        }
      },
    },
    pagerCount: {
      type: Number,
      default: 7,
    },
    textInline: {
      // 表格内容超出后是否换行显示（2020.01.16）
      type: Boolean,
      default: true,
    },
    tableData: {
      // 表数据源,配置了url就不用传这个参数了
      type: Array,
      default: () => {
        return [];
      },
    },
    columns: {
      type: Array,
      default: [],
    },
    height: {
      type: Number,
      default: 0,
    },
    extraHeight: {
      type: Number,
      default: 0,
    },
    maxHeight: {
      type: Number,
      default: 0,
    },
    linkView: {
      type: Function,
      default: function () {
        return 1;
      },
    },
    pagination: {
      type: Object,
      default: function () {
        return { total: 0, size: 30, sortName: "" };
      },
    },
    url: {
      type: String,
      default: "",
    },
    paginationHide: {
      type: Boolean,
      default: true,
    },
    color: {
      type: Boolean,
      default: true,
    },
    index: {
      // 是否创建索引号,如果需要表格编辑功能，这里需要设置为true
      type: Boolean,
      default: false,
    },
    allowEmpty: {
      // 表格数据为空时是否默认为--
      type: Boolean,
      default: true,
    },
    defaultLoadPage: {
      // 传入了url，是否默认加载表格数据
      type: Boolean,
      default: true,
    },
    loadKey: {
      // 是否自动从后台加载数据源
      type: Boolean,
      default: true,
    },
    single: {
      type: Boolean, // 是否单选
      default: false,
    },
    doubleEdit: {
      type: Boolean, // 是否双击启用编辑功能
      default: true,
    },
    beginEdit: {
      // 编辑开始
      type: Function,
      default: function (row, column, index) {
        return true;
      },
    },
    endEditBefore: {
      // 结束编辑前
      type: Function,
      default: function (row, column, index) {
        return true;
      },
    },
    endEditAfter: {
      // 结束编辑前
      type: Function,
      default: function (row, column, index) {
        return true;
      },
    },
    ck: {
      // 是否显示checkbox
      type: Boolean,
      default: true,
    },
    columnIndex: {
      // 是否显示行号(2020..11.1)
      type: Boolean,
      default: true,
    },
    highlightCurrentRow: {
      //增加选中行高亮显示(2022.10.07)
      type: Boolean,
      default: true,
    },
    select2Count: {
      //超出数量显示select2组件
      type: Number,
      default: 1500,
    },
    selectable: {
      type: Function,
      default: (row, index) => {
        return true;
      },
    },
    lazy: {
      //树形表格是否默认延迟加载
      type: Boolean,
      default: true,
    },
    defaultExpandAll: {
      //树形表格是否展开所有
      type: Boolean,
      default: false,
    },
    expandRowKeys: {
      //默认展开行
      type: Array,
      default: () => {
        return [];
      },
    },
    rowParentField: {
      //树形表格父级id
      type: String,
      default: "",
    },
    dragPosition: {
      //2023.11.22
      type: String,
      default: "", //可拖动位置，顶部拖动top,底部bottom
    },
    spanMethod: {
      type: Function,
      default: ({ row, column, rowIndex, columnIndex }, rows) => {},
    },
    reserveSelection: {
      //分页或者刷新表格数据后是否保留复选框选择状态，2024.09.10
      type: Boolean,
      default: false,
    },
    sortable: {
      //表格是否可以拖拽排序
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      fixed: false, //是固定行号与checkbox
      clickEdit: true, //2021.07.17设置为点击行结束编辑
      randomTableKey: 1,
      visiblyColumns: [],
      key: "",
      realHeight: 0,
      realMaxHeight: 0,
      enableEdit: false, // 是否启表格用编辑功能
      empty: this.allowEmpty ? "" : "--",
      defaultImg: new URL("@/assets/imgs/error-img.png", import.meta.url).href,
      //defaultImg:'',// 'this.src="' + require("@/assets/imgs/error.png") + '"',
      loading: false,
      footer: {},
      total: 0,
      formatConfig: {},
      // defaultColor: "",
      // 2020.09.06调整table列数据源的背景颜色
      colors: [null, "success", "success", "danger", "info"],
      rule: {
        phone: /^[1][3,4,5,6,7,8,9][0-9]{9}$/,
        decimal: /(^[\-0-9][0-9]*(.[0-9]+)?)$/,
        number: /(^[\-0-9][0-9]*([0-9]+)?)$/,
      },
      columnNames: [],
      rowData: [],
      paginations: {
        sort: "",
        order: "desc",
        Foots: "",
        total: 0,
        // 2020.08.29增加自定义分页条大小
        sizes: [30, 60, 100, 120],
        size: 30, // 默认分页大小
        Wheres: [],
        page: 1,
        rows: 30,
      },
      errorFiled: "",
      edit: { columnIndex: -1, rowIndex: -1 }, // 当前双击编辑的行与列坐标
      editStatus: {},
      summary: false, // 是否显示合计
      // 目前只支持从后台返回的summaryData数据
      summaryData: [],
      summaryIndex: {},
      remoteColumns: [], // 需要每次刷新或分页后从后台加载字典数据源的列配置
      cellStyleColumns: {}, // 有背景颜色的配置
      fxRight: false, //是否有右边固定表头
      selectRows: [], //当前选中的行
      isChrome: false,
      //vol-table带数据源的单元格是否启用tag标签(下拉框等单元格以tag标签显示)
      //2023.04.02更新voltable与main.js
      useTag: true,
      currentRow: {},
      currentColumn: [],
      fileInfo: [],
      uploadUrl: "",
      uploadModel: false,
      smallCell: true,
      showDragMask: false,
      access_token: "",
      // extraHeight:0
    };
  },
  created() {
    try {
      this.useTag = this.$global.table && this.$global.table.useTag;
      this.smallCell = this.$global.table && this.$global.table.smallCell;
    } catch (error) {
      console.log(error.message);
    }
    const tk = (this.$store.getters.getUserInfo() || { accessToken: "" }).accessToken;
    if (tk) {
      this.access_token = "?access_token=" + tk;
    }

    //2021.06.19判断谷歌内核浏览重新计算table高度
    // if (
    //   navigator.userAgent.indexOf('Chrome') != -1 ||
    //   navigator.userAgent.indexOf('Edge') != -1
    // ) {
    //   this.isChrome = true;
    // }
    this.realHeight = this.getHeight();
    this.realMaxHeight = this.getMaxHeight();
    this.fxRight = this.columns.some((x) => {
      return x.fixed == "right";
    });
    //2021.09.21移除强制固定行号与checkbox列
    if (
      this.columns.some((x) => {
        return x.fixed && x.fixed != "right";
      })
    ) {
      this.fixed = true;
    }
    //2022.04.06优化table合计固定列显示
    // if (
    //   this.columns.some((x) => {
    //     return x.summary;
    //   })
    // ) {
    //   this.columns.forEach((x) => {
    //     if (x.fixed && x.fixed != 'right') {
    //       x.fixed = false;
    //     }
    //   });
    //   this.fixed = false;
    // }
    this.initCellStyle();
    // 从后台加下拉框的[是否启用的]数据源
    let keys = [];
    let columnBind = [];
    // this.summaryData.push(this.$ts('合计'))
    // if (this.columnIndex && this.ck) {
    //   this.summaryData.push(' ')
    // }

    this.initSummaryFields();

    this.columns.forEach((x, _index) => {
      if (x.cellStyle) {
        this.cellStyleColumns[x.field] = x.cellStyle;
      }
      // if (!x.hidden) {
      //   // this.summaryIndex[x.field] = _index;
      //   // 2020.10.11修复求和列错位的问题
      //   this.summaryData.push('')
      //   this.summaryIndex[x.field] = this.summaryData.length - 1
      // }
      // // 求和
      // if (x.summary && !this.summary) {
      //   this.summary = true
      // }

      if (x.children && Array.isArray(x.children)) {
        x.children.forEach((cl) => {
          if (cl.bind && cl.bind.key && (!cl.bind.data || cl.bind.data.length == 0)) {
            keys.push(cl.bind.key);
            cl.bind.valueType = cl.type;
            columnBind.push(cl.bind);
          }
        });
      } else if (x.bind && x.bind.key && (!x.bind.data || x.bind.data.length == 0)) {
        // 写入远程
        if (!x.bind.data) x.bind.data = [];
        if (x.bind.remote) {
          this.remoteColumns.push(x);
        } else if (this.loadKey) {
          keys.push(x.bind.key);
          x.bind.valueType = x.type;
          if (x.edit && x.edit.type) {
            x.bind.editType = x.edit.type;
          }
          columnBind.push(x.bind);
        }
      }
    });
    if (keys.length > 0) {
      this.initDicKeys(keys, columnBind);
    }

    this.paginations.sort = this.pagination.sortName;
    // 2020.08.29增加自定义分页条大小
    Object.assign(this.paginations, this.pagination);
    if (this.pagination.size) {
      this.paginations.rows = this.pagination.size;
    }
    this.enableEdit = this.columns.some((x) => {
      return x.hasOwnProperty("edit");
    });
    let keyColumn = this.columns.find((x) => {
      return x.isKey;
    });
    if (keyColumn) {
      this.key = keyColumn.field;
    }
    this.defaultLoadPage && this.load();
    if (!this.url && this.tableData.length) {
      this.initSummary();
    }
  },
  computed: {
    filterColumns() {
      return this.columns.filter((x, index) => {
        if (!x.field) {
          x.field = x.title + index;
        }
        return !x.hidden;
      });
    },
  },
  methods: {
    initCellStyle() {
      this.columns.forEach((x, _index) => {
        if (x.cellStyle) {
          this.cellStyleColumns[x.field] = x.cellStyle;
        }
      });
    },
    initDicKeys(keys, columnBind) {
      if (!keys || !columnBind) {
        keys = [];
        columnBind = [];
        this.columns.forEach((x, _index) => {
          if (x.children && Array.isArray(x.children)) {
            x.children.forEach((cl) => {
              if (cl.bind && cl.bind.key) {
                keys.push(cl.bind.key);
                columnBind.push(cl.bind);
              }
            });
          } else if (x.bind && x.bind.key) {
            if (this.loadKey) {
              keys.push(x.bind.key);
              columnBind.push(x.bind);
            }
          }
        });
      }
      this.http.post("/api/Sys_Dictionary/GetVueDictionary", keys).then((dic) => {
        dic.forEach((x) => {
          if (x.data.length > this.select2Count) {
            x.data.forEach((item) => {
              item.label = item.value;
              item.value = item.key;
            });
          }
          const arrType = ["cascader", "treeSelect"];
          columnBind.forEach((c) => {
            if (c.key != x.dicNo) {
              return;
            }
            if (arrType.indexOf(c.valueType) != -1 || arrType.indexOf(c.editType) != -1) {
              this.columns.forEach((col) => {
                if (col.bind && col.bind.key == c.key && !col.bind.orginData) {
                  col.bind.orginData = JSON.parse(JSON.stringify(x.data));
                }
              });
              x.data = this.base.convertTree(x.data, (node, data, isRoot) => {
                if (!node.inited) {
                  node.inited = true;
                  node.label = node.value;
                  node.value = node.key + "";
                }
              });
            }
            // 转换数据源的类型与列的类型一致(2020.04.04)
            else if (
              c.key == x.dicNo &&
              (c.valueType == "int" || c.valueType == "sbyte")
            ) {
              x.data.forEach((d) => {
                // 2020.09.01增加对数字类型的二次判断
                if (!isNaN(d.key)) {
                  d.key = ~~d.key;
                }
              });
            }
            if (c.key == x.dicNo) {
              c.data = x.data;
            }
          });
        });
      });
    },
    initSummary() {
      if (!this.summary) {
        return;
      }
      this.columns.forEach((column) => {
        if (column.summary) {
          this.getInputSummaries(null, null, null, column);
        }
      });
    },
    watchRowSelectChange(newLen, oldLen) {
      if (!this.reserveSelection && newLen < oldLen && this.selectRows.length) {
        this.selectRows = [];
        this.$refs.table.clearSelection();
      }
      if (!this.reserveSelection && this.isPageLoad) {
        this.isPageLoad = false;
        return;
      }
      this.initSummary();
    },
    switchChange(val, row, column) {
      //这里在初始化的时候也会触发change事件
      if (Object.keys(row).length <= 1) {
        return;
      }
      if (column.onChange) {
        column.onChange(val, row, column);
      }
    },
    inputKeyPress(row, column, $event, $e) {
      column.onKeyPress && column.onKeyPress(row, column, $event);
      this.getInputSummaries(null, null, $event, column);
    },
    extraClick(row, column) {
      column.extra.click &&
        column.extra.click(row, column, this.url ? this.rowData : this.tableData);
    },
    headerClick(column, event) {
      if (this.clickEdit && this.edit.rowIndex != -1) {
        if (
          this.rowEndEdit(
            this.url
              ? this.rowData[this.edit.rowIndex]
              : this.tableData[this.edit.rowIndex],
            column
          )
        ) {
          this.edit.rowIndex = -1;
        }
      }
      // this.edit.rowIndex = -1;
    },
    rowDbClick(row, column, event) {
      //2021.05.23增加双击行事件
      this.$emit("rowDbClick", { row, column, event });
    },
    rowClick(row, column, event) {
      //2022.02.20增加点击时表格参数判断
      if (!column) {
        return;
      }
      //正在编辑时，禁止出发rowClick事件
      if (this.edit.rowIndex == -1) {
        this.$emit("rowClick", { row, column, event });
      }
      // 点击行事件(2020.11.07)

      if (!this.doubleEdit) {
        return;
      }
      // 点击其他行时，如果点击的行与正在编辑的行相同，保持编辑状态
      if (this.clickEdit && this.edit.rowIndex != -1) {
        if (row.elementIndex == this.edit.rowIndex) {
          // 点击的单元格如果不可以编辑，直接结束编辑
          // 2020.10.12修复结束编辑时，element table高版本属性获取不到的问题
          let _col = this.columns.find((x) => {
            return x.field == ((event && event.property) || column.property);
          });
          if (_col && (!_col.edit || _col.readonly)) {
            if (this.rowEndEdit(row, event)) {
              this.edit.rowIndex = -1;
            }
          }
          return;
        }
        if (this.rowEndEdit(row, event && event.property ? event : column)) {
          this.edit.rowIndex = -1;
        }
        //当正在编辑，且点击到其他行时，在原编辑的行结束编辑后，触发新行的rowClick事件
        //正在编辑时，禁止出发rowClick事件
        if (this.edit.rowIndex == -1) {
          this.$emit("rowClick", { row, column, event });
        }
      }
      this.rowBeginEdit(row, column);
    },
    dowloadFile(file) {
      this.base.dowloadFile(
        file.path + (this.access_token || ""),
        file.name + this.access_token,
        {
          Authorization: this.$store.getters.getToken(),
        },
        this.http.ipAddress
      );
    },
    getFilePath(pathSring, column) {
      // 获取表的图片与文件显示
      if (!pathSring) return [];
      // 增加图片自定义操作
      // 返回格式必须是[{name:"文件名",path:"图片全路径或base64格式"}]
      if (column.formatter) {
        return column.formatter(pathSring);
      }
      let filePath;
      if (column.base64 && pathSring.indexOf("data") != -1) {
        filePath = ("," + pathSring)
          .split(",data")
          .filter((x) => {
            return x;
          })
          .map((m) => {
            return "data" + m;
          });
      } else {
        filePath = pathSring.replace(/\\/g, "/").split(",");
      }

      let fileInfo = [];
      for (let index = 0; index < filePath.length; index++) {
        let file = filePath[index];
        // 2020.12.19增加base64图片显示
        if (column.base64) {
          fileInfo.push({
            name: "",
            path: (file.indexOf("data") == -1 ? "data:image/png;base64," : "") + file,
          });
        } else if (file.indexOf(".") != -1) {
          let splitFile = file.split("/");
          if (splitFile.length > 0) {
            fileInfo.push({
              name: splitFile[splitFile.length - 1],
              path: this.base.isUrl(file) ? file : this.http.ipAddress + file,
            });
          }
        }
      }
      return fileInfo;
    },
    // 重置table
    reset() {
      if (this.tableData && this.tableData.length > 0) {
        this.tableData.splice(0);
      }
      if (this.rowData && this.rowData.length > 0) {
        this.rowData.splice(0);
      }
      if (!this.paginationHide) {
        this.paginations.page = 1;
        // this.paginations.rows = 30;
        if (this.paginations.wheres && this.paginations.wheres.length > 0) {
          this.paginations.wheres.splice(0);
        }
      }

      this.paginations.page = 1;
      this.paginations.total = 0;
      this.errorFiled = "";
      this.edit.columnIndex = -1;
      this.edit.rowIndex = -1;
    },
    getHeight() {
      // 没有定义高度与最大高度，使用table默认值
      if (!this.height && !this.maxHeight) {
        return null;
      }
      // 定义了最大高度则不使用高度
      if (this.maxHeight) {
        return null;
      }
      // 使用当前定义的高度
      return this.height;
    },
    getMaxHeight() {
      // 没有定义高度与最大高度，使用table默认值
      if (!this.height && !this.maxHeight) {
        return null;
      }
      // 定义了最大高度使用最大高度
      if (this.maxHeight) {
        return this.maxHeight;
      }
      // 不使用最大高度
      return null;
    },
    getSelectedOptions(column) {
      if (column.bind && column.bind.data && column.bind.data.length > 0) {
        return column.bind.data;
      }
      return [];
    },
    formatterClick(row, column, event) {
      if (column.click) {
        column.click(row, column, event);
        event.stopPropagation && event.stopPropagation();
      } else {
        this.rowClick(row, column, event);
      }
    },
    initIndex({ row, rowIndex }) {
      if (this.index) {
        row.elementIndex = rowIndex;
      }
      // if (rowIndex%2!==0) {
      //  return "even-row";
      // }
      return;
    },
    toggleEdit(event) {},
    setEditStatus(status) {
      // this.columns.forEach((x) => {
      //   if (x.hasOwnProperty("edit")) {
      //     this.$set(x.edit, "status", status);
      //   }
      // });
    },
    // 通过button按钮启用编辑
    beginWithButtonEdit(scope) {
      // url?rowData:tableData
      this.rowBeginEdit(scope.row, this.columns[scope.$index]);
    },
    rowBeginEdit(row, column) {
      if (this.edit.rowIndex != -1) {
        return;
      }
      let _col = this.columns.find((x) => x.field == column.property);
      if (_col) {
        if (_col.readonly && (_col.click || _col.render)) {
          return;
        }
        if (
          //不能编辑的字段、switch，点击不开启启编辑功能
          !_col.edit ||
          (_col.edit.keep && _col.edit.type == "switch")
        ) {
          return;
        }
      }
      if (!this.enableEdit) return;
      _errMsg = "";
      // 编辑前
      this.columns
        .filter((x) => {
          return x.bind && x.bind.data && x.bind.data.length;
        })
        .forEach((column) => {
          let val = row[column.field];
          if (typeof column.bind.data[0].key == "string") {
            if (typeof val == "number") {
              row[column.field] = row[column.field] + "";
            }
          } else {
            //2024.01.10修复多选、级联编辑时类型转换的问题
            if (Array.isArray(val)) {
              val = val.map((v) => {
                return v * 1;
              });
              row[column.field] = val;
            } else if (typeof val == "string" && val) {
              let _val = val * 1;
              if (_val + "" === val) {
                row[column.field] = _val;
              }
            }
          }
        });
      if (!this.beginEdit(row, column, row.elementIndex)) return;
      if (row.hasOwnProperty("elementIndex")) {
        if (this.edit.rowIndex == row.elementIndex) {
          return;
        }
        this.edit.rowIndex = row.elementIndex;
      }
      let col = this.columns.find((x) => {
        return x.field == (column.field || column.property);
      });
      if (col && col.edit) {
        if (col.edit.type == "cascader" && !col.bind.orginData) {
          col.bind.orginData = col.bind.data;
          col.bind.data = this.base.convertTree(col.bind.data, (node, data, isRoot) => {
            //  node.value = node.value;
            node.label = node.value;
            // node.text = node.name;
          });
        }
        //&&x.edit&&x.edit.type=='selectTable'
        this.$nextTick(() => {
          let refEl = this.$refs[(column.field || column.property) + row.elementIndex];
          if (refEl && Array.isArray(refEl)) {
            refEl[0].focus && refEl[0].focus();
          }
        });
      }
    },
    rowEndEdit(row, column, event) {
      if (this.clickEdit && event) {
        return true;
      }
      if (!this.enableEdit) {
        if (!this.errorFiled) {
          if (
            this.edit.rowIndex != -1 &&
            !this.endEditAfter(row, column, this.edit.rowIndex)
          ) {
            return false;
          }
          this.edit.rowIndex = -1;
        }
        return true;
      }
      if (!this.doubleEdit && event) {
        return true;
      }
      let _row = this.url
        ? this.rowData[this.edit.rowIndex]
        : this.tableData[this.edit.rowIndex];
      // 结束编辑前
      if (!this.endEditBefore(_row, column, this.edit.rowIndex)) return false;
      if (this.edit.rowIndex != -1) {
        //2022.06.26修复表格内容切换后行数不一致时不能编辑的问题
        if (this.edit.rowIndex - 1 > (this.rowData || this.tableData).length) {
          this.edit.rowIndex = -1;
          return;
        }
        let row = (this.url ? this.rowData : this.tableData)[this.edit.rowIndex];
        for (let index = 0; index < this.columns.length; index++) {
          const _column = this.columns[index];
          if (_column.edit) {
            if (!this.validateRow(row, _column)) {
              return;
            }
          }
        }
      }
      if (!this.endEditAfter(_row, column, this.edit.rowIndex)) return false;
      this.edit.rowIndex = -1;
      return true;
    },
    validateRow(row, option1) {
      if (!this.validateColum(option1, row)) {
        this.errorFiled = option1.field;
        // 2022.05.06 修改错误信息重复的问题
        this.$message.error(this.$ts(option1.title) + _errMsg);
        return false;
      }
      this.errorFiled = "";
      return true;
    },
    validateColum(option, data) {
      if (option.hidden || option.bind) return true;
      let val = data[option.field];
      if (option.require || option.required) {
        if (val != "0" && (val === "" || val === undefined)) {
          if (!this.errorFiled) {
            _errMsg = this.$ts("不能为空");
          }
          return false;
        }
      }
      if (!option.edit) {
        return true;
      }
      let editType = option.edit.type;
      // 验证数字
      if (editType == "int" || editType == "decimal" || editType == "number") {
        if (val == "" || val == undefined) return true;
        if (editType == "decimal") {
          if (!this.rule.decimal.test(val)) {
            _errMsg = this.$ts("只能是数字");
            return false;
          }
        } else if (!this.rule.decimal.test(val)) {
          _errMsg = this.$ts("只能是数字");
          return false;
        }
        if (
          option.edit.min != undefined &&
          typeof option.edit.min === "number" &&
          val < option.edit.min
        ) {
          _errMsg = this.$ts("不能小于") + option.edit.min;
          return false;
        }
        if (
          option.edit.max != undefined &&
          typeof option.edit.max === "number" &&
          val > option.edit.max
        ) {
          _errMsg = this.$ts("不能大于") + option.edit.max;
          return false;
        }
        return true;
      }

      // 验证字符串
      if (val && (editType == "text" || editType == "string")) {
        //   if (
        //     option.edit.min != undefined &&
        //     typeof option.edit.min === "number" &&
        //     val.length < option.edit.min
        //   ) {
        //     _errMsg = "至少" + option.edit.min + "个字符";
        //     return false;
        //   }
        //   if (
        //     option.edit.max != undefined &&
        //     typeof option.edit.max === "number" &&
        //     val.length > option.edit.max
        //   ) {
        //     _errMsg = "最多" + option.edit.max + "个字符";
        //     return false;
        //   }
      }
      return true;
    },
    delRow() {
      let rows = this.getSelected();
      if (rows.length == 0) return this.$Message.error(this.$ts("请选择要删除的行!"));

      let data = this.url ? this.rowData : this.tableData;
      let indexArr = this.getSelectedIndex();
      if (indexArr.length == 0) {
        return this.$Message.error("删除操作必须设置VolTable的属性index='true'");
      }
      // if (indexArr.length == 0 || !this.key) {
      //   return this.$message.error(
      //     "请设置index=true属性或指columns的字段为key"
      //   );
      // }
      if (indexArr.length == 0) {
        // let keyValues=[]
        // rows.forEach(x=>{
        //   if (x[this.key]) {
        //   }
        //   keyValues.push(x[this.key])
        // })
        // data.find(x=>)
      } else {
        for (let i = data.length - 1; i >= 0; i--) {
          if (indexArr.indexOf(i) != -1) {
            data.splice(i, 1);
          }
        }
      }
      this.edit.rowIndex = -1;
      return rows;
    },
    addRow(row) {
      if (!row) {
        row = {};
      }
      this.columns.forEach((x) => {
        // 2022.05.06 添加行时，如果列有编辑属性，设置开启编辑(避免关闭编辑后，无法再次启用编辑)??
        //x.readonly = false;
        if (!row.hasOwnProperty(x.field)) {
          if (x.edit && x.edit.type == "switch") {
            row[x.field] = x.type == "bool" ? false : 0;
          } else if (!row.hidden) {
            // 2020.09.06添加行时，设置默认字段
            row[x.field] = undefined;
          }
        }
      });
      if (!this.url) {
        this.tableData.push(row);
        return;
      }
      this.rowData.push(row);
    },
    viewImg(row, column, url, $event, index) {
      $event && $event.stopPropagation();
      const imgs = this.getFilePath(row[column.field], column).map((x) => {
        return x.path + this.access_token;
      });
      this.$refs.viewer.show(imgs, index);
      //this.base.previewImg(url);
      // window.open(row[column.field]);
    },
    link(row, column, $e) {
      $e.stopPropagation();
      this.$props.linkView(row, column);
    },
    getSelected() {
      return this.selectRows;
    },
    getSelectedIndex() {
      if (!this.index) {
        // 只有设置了属性index才有索引行
        return [];
      }
      let indexArr = this.selectRows.map((x) => {
        return x.elementIndex;
      });
      return indexArr || [];
    },
    GetTableDictionary(rows) {
      // 分页或刷新或重新绑定数据源
      if (this.remoteColumns.length == 0 || !rows || rows.length == 0) return;
      let remoteInfo = {};
      for (let index = 0; index < this.remoteColumns.length; index++) {
        const column = this.remoteColumns[index];
        //  column.bind.data.splice(0);
        let key = column.bind.key;
        let data = [];
        rows.forEach((row) => {
          if (row[column.field] || row[column.field] == "0") {
            if (data.indexOf(row[column.field]) == -1) {
              data.push(row[column.field]);
            }
          }
        });
        if (data.length > 0) {
          remoteInfo[key] = data;
        }
      }
      if (remoteInfo.length == 0) return;
      // ha= Object.assign([], ha, hb)
      this.http.post("/api/Sys_Dictionary/GetTableDictionary", remoteInfo).then((dic) => {
        dic.forEach((x) => {
          this.remoteColumns.forEach((column) => {
            if (column.bind.key == x.key) {
              column.bind.data = Object.assign([], column.bind.data, x.data);
              // column.bind.data.push(...x.data);
            }
          });
        });
        this.$emit("dicInited", dic);
      });
    },
    load(query, isResetPage) {
      // isResetPage重置分页数据
      if (!this.url) return;
      if (isResetPage) {
        this.resetPage();
      }
      let param = {
        page: this.paginations.page,
        rows: this.paginationHide ? 1000 : this.paginations.rows,
        sort: this.paginations.sort,
        order: this.paginations.order,
        wheres: [], // 查询条件，格式为[{ name: "字段", value: "xx" }]
      };
      let status = true;
      // 合并查询信息(包查询分页、排序、查询条件等)
      if (query) {
        param = Object.assign(param, query);
      }
      /* 查询前处理(如果需要查询条件，实现组件方法loadBefore方法即可:
        loadBefore=(param, callBack)=>{
          param.wheres = [{ name: "PhoneNo", value: "13419098211" }];
          callBack(true);
        })
      */
      this.$emit("loadBefore", param, (result) => {
        status = result;
      });
      if (!status) return;

      if (param.wheres && param.wheres instanceof Array) {
        param.wheres = JSON.stringify(param.wheres);
      }
      this.loading = true;
      let url = param.url || this.url;
      param.url = undefined;
      this.http.post(url, param).then(
        (data) => {
          if (Array.isArray(data)) {
            data = { rows: data, total: data.length };
          }
          //2021.06.04修复tree不刷新的问题
          if (this.rowKey) {
            this.randomTableKey++;
            this.rowData.splice(0);
          }
          this.loading = false;
          // 查询返回结果后处理
          // 2020.10.30增加查询后返回所有的查询信息
          this.$emit(
            "loadAfter",
            data.rows,
            (result) => {
              status = result;
            },
            data
          );
          if (!status) return;
          this.GetTableDictionary(data.rows);
          let rows = data.rows || [];
          if (this.rowParentField) {
            rows = this.base.convertTree(rows, null, this.rowKey, this.rowParentField);
          }
          if (this.rowData.length !== rows.length) {
            this.isPageLoad = true;
          }
          this.rowData = rows;
          this.paginations.total = data.total || 0;
          // 合计
          this.getSummaries(data);
          //设置分页后记录默认选中行2024.09.10
          if (this.reserveSelection && this.rowKey) {
            // this.isPageLoad = false;
            this.$nextTick(() => {
              this.isPageLoad = true;
              rows.forEach((row) => {
                if (
                  this.selectRows.some((c) => {
                    return c[this.rowKey] === row[this.rowKey];
                  })
                ) {
                  this.$refs.table.toggleRowSelection(row);
                }
              });
              this.isPageLoad = false;
            });
          }
          // this.$nextTick(() => {
          //   this.$refs.table.doLayout();
          // });
        },
        (error) => {
          this.loading = false;
          // this.$Message.error(error || "网络异常");
        }
      );
    }, // 获取统计
    getSummaries(data) {
      // if (!this.summary || !data.summary) return;
      if (!this.summary) return;
      this.summaryData.splice(0);
      // 开启了行号的，+1
      if (this.columnIndex) {
        this.summaryData.push("");
      }
      // 如果有checkbox，应该算作是第一行
      if (this.ck) {
        this.summaryData.push("");
      }

      this.columns.forEach((col) => {
        if (col.children && col.children.length) {
          col.children.forEach((item) => {
            this.getColumnSummaries(item, data);
          });
        } else {
          this.getColumnSummaries(col, data);
        }
      });
      if (this.summaryData.length > 0 && this.summaryData[0] == "") {
        this.summaryData[0] = this.$ts("合计");
      }
    },
    getColumnSummaries(col, data) {
      if (!col.hidden) {
        if (data.summary && data.summary.hasOwnProperty(col.field)) {
          let sum = data.summary[col.field] * 1.0;
          //2024.01.07增加自定义合计格式化
          if (col.summaryFormatter) {
            sum = col.summaryFormatter(sum, col, data.rows || data, this.summaryData);
          } else if (sum) {
            sum = (sum * 1.0).toFixed(col.numberLength || 2);
            sum = parseFloat(sum).toString();
          }
          this.summaryData.push(sum);
        } else {
          this.summaryData.push("");
        }
      }
    },
    getInputChangeSummaries() {},
    handleSizeChange(val) {
      this.paginations.size = val;
      this.paginations.rows = val;
      this.load();
    },
    handleCurrentChange(val) {
      this.paginations.page = val;
      this.load();
    },
    sortChange(sort) {
      if (!this.url) {
        this.tableData.sort(function (a, b) {
          if (sort.order == "ascending") {
            return a[sort.prop] - b[sort.prop];
          }
          return b[sort.prop] - a[sort.prop];
        });
        return;
      }
      this.paginations.sort = sort.prop;
      this.paginations.order = sort.order == "ascending" ? "asc" : "desc";
      this.load();
    },
    resetPage() {
      // 重置查询分页
      // this.paginations.rows = 30;
      this.paginations.page = 1;
    },
    selectionChange(selection) {
      // console.log(selection);
      // 选择行事件,只有单选才触发
      if (this.reserveSelection && this.rowKey) {
        //分页或者刷新时不重置选中的数据
        if (!this.isPageLoad) {
          //获取当前页选中的行数据并且未添加的数据
          const selectNewRows = selection.filter((c) => {
            return !this.selectRows.some((x) => {
              return x[this.rowKey] === c[this.rowKey];
            });
          });
          //当前面新添加的数据
          this.selectRows.push(...selectNewRows);
          //获取当前页移除(未选中)的数据
          let unselectIds = (this.url ? this.rowData : this.tableData)
            .filter((x) => {
              return !selection.some((c) => {
                return x[this.rowKey] === c[this.rowKey];
              });
            })
            .map((c) => {
              return c[this.rowKey];
            });
          this.selectRows = this.selectRows.filter((c) => {
            return !unselectIds.some((x) => x === c[this.rowKey]);
          });
          //  console.log(this.selectRows);
        }
      } else {
        this.selectRows = selection;
      }
      if (this.single) {
        if (selection.length == 1) {
          this.$emit("rowChange", selection[0]);
        }
        if (selection.length > 1) {
          let _row = selection[selection.length - 1];
          this.$refs.table.toggleRowSelection(selection[0]);
          this.selectRows = [_row];
        }
      } else {
        this.$emit("rowChange", selection);
      }
      // 将selectionchange暴露出去
      this.$emit("selectionChange", selection);
    },
    getColor(row, column) {
      let val = row[column.field];
      if (column.getColor && typeof column.getColor === "function") {
        let _color = column.getColor(row, column);
        if (_color) {
          return _color;
        }
      }
      if (!val && val != "0") {
        return null;
      }
      if (!this.formatConfig[column.field]) {
        this.formatConfig[column.field] = [val];
        return this.colors[0];
      }
      let index = this.formatConfig[column.field].indexOf(val);
      if (index != -1) {
        return this.colors[index];
      }
      if (this.formatConfig[column.field].length > 5) {
        return null;
      }

      if (index == -1) {
        this.formatConfig[column.field].push(val);
        index = this.formatConfig[column.field].length - 1;
      }
      return this.colors[index];
    },
    formatterDate(row, column) {
      return (row[column.field] || "").substr(0, 10);
    },
    formatter(row, column, template) {
      if (!template) return row[column.property];
      let val = row[column.field];
      if (!val && val != 0) return val;
      // 是否值
      if (column.edit && column.edit.type == "switch") {
        return this.$ts(val ? "是" : "否");
      }
      if (!column.bind || !column.bind.data) {
        return row[column.field];
      }
      //2024.05.28增加级联显示完整路径
      if (column.type == "cascader" && this.$global.table.cascaderFullPath !== false) {
        if (column.bind.orginData && column.bind.orginData.length) {
          return this.base
            .getTreeAllParent(val, column.bind.orginData)
            .map((c) => {
              return c.value;
            })
            .join(column.separator || " / ");
        } else {
          if (column.bind.data) {
            let fullValue = this.base
              .getTreeAllParent(val, column.bind.data)
              .map((c) => {
                return c.value;
              })
              .join(column.separator || " / ");
            if (fullValue && fullValue !== val) {
              return fullValue;
            }
          }
        }
      }

      if (
        column.edit &&
        (column.edit.type == "selectList" ||
          column.edit.type == "checkbox" ||
          column.edit.type == "cascader" ||
          column.edit.type == "treeSelect")
      ) {
        if (!Array.isArray(val)) {
          row[column.field] = (val + "").split(",");
        } else {
          val = val.join(",");
        }
        return this.getSelectFormatter(column, val);
      }
      // 编辑多选table显示
      // if (
      //   column.bind.type == "selectList" ||
      //   column.bind.type == "checkbox" ||
      //   column.bind.type == "cascader" ||
      //   column.bind.type == "treeSelect"
      // ) {
      //   // if (typeof val === 'string' && val.indexOf(',') != -1) {
      //   return this.getSelectFormatter(column, val + "");
      //   //  }
      // }
      if ((val + "").indexOf(",") != -1) {
        return this.getSelectFormatter(column, val);
      }
      let source = column.bind.data.filter((x) => {
        // return x.key != "" && x.key == val;
        // 2020.06.06修复单独使用table组件时,key为数字0时转换成文本失败的问题
        return x.key !== "" && x.key !== undefined && x.key + "" === val + "";
      });
      if (source && source.length > 0) val = source[0].label || source[0].value;
      return this.$ts(val);
    },
    getSelectFormatter(column, val) {
      // 编辑多选table显示
      let valArr = (val + "").split(",");
      for (let index = 0; index < valArr.length; index++) {
        (column.bind.orginData && column.bind.orginData.length
          ? column.bind.orginData
          : column.bind.data
        ).forEach((x) => {
          // 2020.06.06修复数据源为selectList时,key为数字0时不能转换文本的问题
          if (x.key !== "" && x.key !== undefined && x.key + "" == valArr[index] + "") {
            valArr[index] = x.label || this.$ts(x.value);
          }
        });
      }
      return valArr.join(",");
    },
    onChange(scope, val, event, column) {
      // 2020.09.03修复onChange不触发的问题
      let row = scope.row;
      if (column.onChange && !column.onChange(row, val, event)) {
        return;
      }
      // 输入框求和实时计算
      this.getInputSummaries(scope, val, event, column);
    },
    updateSummary(field) {
      //2024.03.05增加手动刷新合计方法
      let column = this.columns.find((x) => {
        return x.field == field;
      });
      if (!column) {
        return;
      }
      this.getInputSummaries(null, null, null, column);
    },
    // input输入实时求和
    getInputSummaries(scope, val, event, column) {
      // column列设置了summary属性的才计算值
      if (!column.summary) return;
      let sum = 0;
      //  let _index = 0;
      (this.url ? this.rowData : this.tableData).forEach((x, index) => {
        if (x.hasOwnProperty(column.field) && !isNaN(x[column.field])) {
          // _index = index;
          sum += x[column.field] * 1;
        }
      });

      if (column.summaryFormatter) {
        sum = column.summaryFormatter(
          sum,
          column,
          this.url ? this.rowData : this.tableData,
          this.summaryData
        );
      } else {
        sum = sum * 1.0;
        if (sum) {
          if (column.summary == "avg") {
            sum = sum / (this.rowData.length || this.tableData.length || 1);
          }
          sum = (sum * 1.0).toFixed(column.numberLength || 2);
          sum = parseFloat(sum).toString();
        }
      }

      this.summaryData[this.summaryIndex[column.field]] = sum;
    },
    getSummaryData({ columns, data }) {
      return this.summaryData;
    },
    getCellClass({ row, column, rowIndex, columnIndex }) {
      if (
        this.columns.some((x) => {
          return (
            x.field === column.property &&
            x.edit &&
            (x.edit.keep || this.edit.rowIndex === rowIndex)
          );
        })
      ) {
        return "current-edit-cell";
      }
      if (this.columns[columnIndex]) {
        return this.columns[columnIndex].class;
      }
    },
    getCellStyle(row) {
      // 2020.12.13增加设置单元格颜色
      if (row.column.property) {
        return (
          this.cellStyleColumns[row.column.property] &&
          this.cellStyleColumns[row.column.property](
            row.row,
            row.rowIndex,
            row.columnIndex,
            this.rowData
          )
        );
      }
    },
    compareDate(date1, date2) {
      if (!date2) {
        return true;
      }
      return (
        date1.valueOf() < (typeof date2 == "number" ? date2 : new Date(date2).valueOf())
      );
    },
    getDateOptions(date, item) {
      //2021.07.17设置时间可选范围
      if ((!item.min && !item.max) || !date) {
        return false;
      }
      if (item.min && item.min.indexOf(" ") == -1) {
        //不设置时分秒，后面会自动加上 08:00
        item.min = item.min + " 00:00:000";
      }
      return this.compareDate(date, item.min) || !this.compareDate(date, item.max);
    },
    getDateFormat(column) {
      if (column.format) {
        return column.format;
      }
      if (column.edit.type == "month") {
        return "YYYY-MM";
      }
      //见https://day.js.org/docs/zh-CN/display/format
      return column.edit.type == "date" ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm:ss";
    },
    userSelect(selection, row) {
      // this.selectRows = selection;
      // if (!this.single) {
      //   this.$emit("rowChange", { row, selection });
      // }
    },
    isEmptyTag(row, column) {
      if (!row[column.field] && row[column.field] != "0") {
        return "empty-tag";
      }
      return "";
    },
    filterChildrenColumn(children) {
      if (!children) {
        return [];
      }
      return children.filter((x) => {
        return !x.hidden;
      });
    },
    initColumnDisabled(row, column) {
      return column.getDisabled && column.getDisabled(row, column);
    },
    showUpload(row, column) {
      this.fileInfo = (row[column.field] || "")
        .split(",")
        .filter((x) => {
          return x;
        })
        .map((item) => {
          return { path: item, name: "" };
        });
      this.currentRow = row;
      this.currentColumn = column;
      if (this.currentColumn.edit.autoUpload === undefined) {
        this.currentColumn.edit.autoUpload = true;
      }
      if (this.currentColumn.edit.multiple === undefined) {
        this.currentColumn.edit.multiple = false;
      }

      if (this.currentColumn.edit.url === undefined) {
        this.uploadUrl =
          "api/" + (this.url || "").replace("/api", "api").split("/")[1] + "/upload";
      } else {
        this.uploadUrl = this.currentColumn.edit.url;
      }
      this.uploadModel = true;
    },
    uploadBefore(files, params) {
      if (!this.currentColumn.uploadBefore) {
        return true;
      }
      return this.currentColumn.uploadBefore(files, params, this.currentRow);
    },
    uploadAfter(result, files) {
      if (!this.currentColumn.uploadAfter) {
        return true;
      }
      return this.currentColumn.uploadAfter(result, files, this.currentRow);
    },
    uploadOnChange(files) {
      if (!this.currentColumn.onChange) {
        return true;
      }
      return this.currentColumn.onChange(files, this.currentRow);
    },
    saveUpload() {
      //生成保存后返回的路径
      let arr = this.fileInfo.map((x) => {
        if (x.path) {
          return x.path;
        }
        return result.data + x.name;
      });

      this.currentRow[this.currentColumn.field] = arr.join(",");
      this.uploadModel = false;
      return true;
    },
    handleTableClickOutside(event) {
      if (this.$refs.refTable && !this.$refs.refTable.contains(event.target)) {
        if (this.isDateChange) {
          //this.isDateChange = false;
          return;
        }
        if (this.edit.rowIndex != -1) {
          let row = this.url
            ? this.rowData[this.edit.rowIndex]
            : this.tableData[this.edit.rowIndex];
          this.rowEndEdit(row);
          this.edit.rowIndex = -1;
        }
      }
    },
    dateVisibleChang(show) {
      this.isDateChange = show;
    },
    dateChange(row, column, val) {
      this.isDateChange = true;
      column.onChange && column.onChange(row, column, val);
    },
    expandChange(row, expandedRows) {
      //	当用户对某一行展开或者关闭的时
      if (!this.defaultExpandAll && !this.lazy) {
        if (expandedRows) {
          if (this.expandRowKeys.indexOf(row[this.rowKey]) == -1) {
            this.expandRowKeys.push(row[this.rowKey] + "");
          }
        } else {
          let _index = this.expandRowKeys.findIndex((x) => {
            return x == row[this.rowKey];
          });
          if (_index != -1) {
            this.expandRowKeys.splice(_index, 1);
          }
        }
      }
    },
    onBlur(row, column, $event) {
      column.blur && column.blur(row, column, $event);
    },
    onFocus(row, column, $event) {
      column.focus && column.focus(row, column, $event);
    },
    initDrag() {
      if (!this.dragPosition) {
        return;
      }
      var oDragIcon = this.$refs.drag;
      const refTable = this.$refs.refTable;
      var disY = 0;
      oDragIcon.onmousedown = (ev) => {
        this.showDragMask = true;
        var ev = ev || window.event;
        disY = ev.clientY; // 获取鼠标按下时光标Y的值
        let disH = refTable.offsetHeight; // 获取拖拽前div的高
        document.onmousemove = (ev) => {
          var ev = ev || window.event;
          var H = ev.clientY - disY + disH;
          if (H < 100) {
            H = 100;
          }
          if (H > 600) {
            H = 600;
          }
          this.realHeight = H;
        };
        document.onmouseup = () => {
          setTimeout(() => {
            this.showDragMask = false;
          }, 400);
          document.onmousemove = null;
          document.onmouseup = null;
        };
      };
    },
    cellSpanMethod({ row, column, rowIndex, columnIndex }) {
      return this.spanMethod(
        { row, column, rowIndex, columnIndex },
        this.url ? this.rowData : this.tableData
      );
    },
    handleImageError($e) {
      $e.target.src = this.defaultImg;
    },
    toNextCell(tableName, row, nextField, newRow) {
      //2024.07.05按回车键后自动跳转到下一行指定字段并获取焦点
      for (let index = 0; index < this.columns.length; index++) {
        const _column = this.columns[index];
        if (_column.edit) {
          if (!this.validateRow(row, _column)) {
            return;
          }
        }
      }
      let currentIndex = row.elementIndex + 1;
      let rows = this.url ? this.rowData : this.tableData;
      if (rows.length == currentIndex) {
        //没有下一行并且不需要自动添加行直接返回
        if (!newRow) {
          return;
        }
        //添加新的一行
        this.addRow();
      }
      this.edit.rowIndex = currentIndex;
      setTimeout(() => {
        this.$refs[nextField + currentIndex][0].focus();
      }, 400);
    },
    getFilters(column) {
      let arr = [];
      let rows = this.url ? this.rowData : this.tableData;
      for (let index = 0; index < rows.length; index++) {
        const row = rows[index];
        if (
          !arr.some((c) => {
            return c.value === row[column.field];
          })
        ) {
          let obj = { text: this.formatter(row, column, true), value: row[column.field] };
          arr.push(obj);
        }
      }
      return arr;
    },
    filterHandler(value, row, column) {
      return row[column.property] === value;
    },
    initSummaryFields() {
      this.summaryData.splice(0);
      this.summaryIndex = {};
      this.summaryData.push(this.$ts("合计"));
      if (this.columnIndex && this.ck) {
        this.summaryData.push(" ");
      }
      this.columns.forEach((x, _index) => {
        if (!x.hidden) {
          // 2020.10.11修复求和列错位的问题
          this.summaryData.push("");
          this.summaryIndex[x.field] = this.summaryData.length - 1;
        }
        // 求和
        if (x.summary && !this.summary) {
          this.summary = true;
        }
      });
    },
    clearSelection() {
      this.$refs.table.clearSelection();
      this.selectRows = [];
    },
    toggleRowSelection(row) {
      this.$refs.table.toggleRowSelection(row);
    },
    initSortable() {
      if (!this.sortable) {
        return;
      }
      const tbody = this.$refs.refTable.querySelectorAll(
        ".el-table__body-wrapper tbody"
      )[0];
      Sortable.create(tbody, {
        disabled: false,
        animation: 150,
        group: {
          pull: false,
          put: false,
        },
        onEnd: ({ newIndex, oldIndex }) => {
          let rows = this.rowData.length ? this.rowData : this.tableData;
          rows.splice(newIndex, 0, rows.splice(oldIndex, 1)[0]);
          const newArr = rows.splice(0);
          this.$nextTick(() => {
            rows.push(...newArr);
            this.$emit("onSortEnd", rows, newIndex, oldIndex);
          });
        },
      });
    },
    selectChange(row, column, value, isClear) {
      if (isClear) {
        row[column.field] = column.edit.type == "select" ? null : [];
      }
      column.onChange && column.onChange(row, column, isClear);
    },
  },
  mounted() {
    this.initDrag();
    if (
      this.columns.some((x) => {
        return x.edit;
      })
    ) {
      document.addEventListener("click", this.handleTableClickOutside);
    }
    this.initSortable();
  },
  unmounted() {
    if (
      this.columns.some((x) => {
        return x.edit;
      })
    ) {
      window.removeEventListener("click", this.handleTableClickOutside);
    }
  },
});
</script>
<style lang="less" scoped>
.vol-table {
  position: relative;
  .mask {
    opacity: 0.2;
    position: absolute;
    width: 100%;
    height: 100%;
    background: #d0d0d033;
    z-index: 100;
  }
  .message {
    // text-align: center;
    // color: #aaaaaa;
    // font-size: 13px;
    // font-weight: 600;
    // background: #ffffff;
    // transform: translateY(-50%);
    // top: 50%;
    position: absolute;
    width: 100%;
    height: 100%;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    // left: 0;
    // right: 0;
    // width: 100px;
    // margin: 0 auto;
    // line-height: 100px;
    // border-radius: 5px;
    // border: 1px solid #ededed87;
    div {
      height: 70px;
      margin-top: 30px;
      padding: 5px 10px;
      background: #ffff;
      border-radius: 2px;
      display: flex;
      align-items: center;
      width: 130px;
      justify-content: center;
    }
  }
}
.e-item {
  display: flex;
  > div:first-child {
    flex: 1;
  }
}
.vol-table ::v-deep(.el-pager .number) {
  padding: 0 7px;
  border-radius: 3px;
  border: 1px solid #e6e6e6;
  margin-left: 8px;
  font-weight: 500;
  min-width: 27px;
  height: 25px;
  font-size: 13px;
}
.vol-table ::v-deep(.el-pager .number.active) {
  background: #ed4014;
  color: #fff;
}
.vol-table .t-file {
  color: #1e8cff;
  cursor: pointer;
  border-bottom: 1px solid;
  padding-bottom: 2px;
}
.vol-table .empty-tag {
  border: none;
  background: none;
}
.v-table ::v-deep(.el-date-editor .el-icon-date),
.v-table ::v-deep(.el-date-editor .el-icon-time) {
  width: 10px;
}

.column-required {
  position: relative;
  color: #f20303;
  font-size: 14px;
  top: 2px;
  right: 2px;
}
</style>

<style scoped>
/* .v-table ::v-deep(.even-row){
  background: rgb(245,247,250);
} */
.pagination {
  text-align: right;
  padding: 2px 28px;
  border: 1px solid #eee;
  border-top: 0px;
}
/* .v-table ::v-deep(.el-input .el-input__inner) {
  padding: 0 7px;
} */
.v-table ::v-deep(.el-table__header th) {
  /* padding: 0px !important; */
  background-color: #f8f8f9 !important;
  font-size: 13px;
  /* height: 46px; */
  color: #000;
}

.v-table ::v-deep(.el-table__header th.is-sortable) {
  padding: 3px !important;
}
.vol-table.text-inline ::v-deep(.el-table__body .cell),
.vol-table.text-inline ::v-deep(.el-table__header-wrapper .cell) {
  word-break: inherit !important;
  white-space: nowrap !important;
}
/* .v-table  ::v-deep(.el-table__body td) {
  padding: 9px 0 !important;
} */

.v-table ::v-deep(.el-table__footer td) {
  padding: 7px 0 !important;
}

.vol-table ::v-deep(.el-table-column--selection .cell) {
  display: inline;
  line-height: 1.2;
}
.vol-table.text-inline ::v-deep(.el-table th > .cell) {
  white-space: nowrap !important;
}

.vol-table .table-img {
  height: 40px;
  border-radius: 5px;
  margin-right: 10px;
  width: 40px;
  object-fit: cover;
}
.vol-table .table-img:hover {
  cursor: pointer;
}

.vol-table ::v-deep(.cell) {
  padding: 2px 10px;
  min-height: 27px;
}
.vol-table ::v-deep(.cell .el-tag) {
  padding: 5px 9px;
}

.table-input {
  color: rgb(104, 103, 103);
  padding: 3px 6px;
  height: 30px;
  line-height: 30px;
  width: 100%;
  border-radius: 4px;
  border: 1px solid #dcdcdc;
}
.table-input:focus {
  outline: 1px solid #49a3fd;
}

.small-table ::v-deep(.el-pagination .el-input__wrapper) {
  height: 25px;
  border-radius: 3px;
}

.small-table ::v-deep(.el-pagination .el-select .el-input) {
  width: 90px;
}
.small-table ::v-deep(.el-pagination .el-pagination__editor) {
  width: 45px;
}

::v-deep(.el-input__wrapper) {
  padding: 1px 7px;
}
.small-table ::v-deep(input) {
  font-size: 13px;
}
.small-table ::v-deep(.el-table__cell) {
  padding: 0px 0;
  font-size: 13px;
  height: 37px;
}
.small-table ::v-deep(.cell-tag) {
  padding: 0 5px !important;
  height: 19px;
}
.small-table ::v-deep(.current-edit-cell.el-table__cell .cell) {
  padding: 1px 3px;
}
.vol-table-upload ::v-deep(.upload-container) {
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.el-drag {
  height: 16px;
  width: 100%;
  cursor: n-resize;
  /* background: #4545cf; */
  position: absolute;
  z-index: 999999;
  bottom: 2px;
}
.drag-mask {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 99;
  background: #ffff;
  opacity: 0;
}
</style>
